//
//  MoreLoading.swift
//  dcloudlive
//
//  Created by zhu xietong on 2020/4/1.
//  Copyright © 2020 douyun. All rights reserved.
//

import UIKit
import Eelay

open class MoFooterLoading: UIView {
    public enum Status {
        case end
        case loading
        case waiting
    }
    
    public enum Direction {
        case vertical
        case horizontal
        func endDistance(scrollView:UIScrollView) -> CGFloat{
            switch self {
            case .vertical:
//                print("+==OO==\(scrollView.contentOffset)=====\(scrollView.contentSize)")
                return scrollView.contentSize.height - scrollView.mj_offsetY - scrollView.bounds.height
            default:
                return scrollView.contentSize.width - scrollView.mj_offsetX - scrollView.bounds.width
            }
        }
    }
    
    open class Content: MoDisplayNode {
        public var direction:Direction = .vertical
        public var indicatorNode = ASDisplayNode { () -> UIView in
            if #available(iOS 13.0, *) {
                return UIActivityIndicatorView(style: .medium)
            } else {
                return UIActivityIndicatorView(style: .gray)
            }
        }
        public var indicator:UIActivityIndicatorView?{
            get{
                return indicatorNode.view as? UIActivityIndicatorView
            }
        }
        
        public var status = Status.waiting{
            didSet{
                setNeedsLayout()
                layoutIfNeeded()
                switch status {
                case .loading:
                    indicator?.startAnimating()
                default:
                    indicator?.stopAnimating()
                }
            }
        }
        public var textNode = ASTextNode2()
        public var loadingText:String? = nil
        open override func specGetter() -> _Spec {
            
            var spec:[_Spec] = [
                indicatorNode[40,40],
            ]
           
            switch direction {
            case .horizontal:
                return .inset([], [8], child: .stack(["h|6",&-.center,_justfy(.center)], childs: spec))
            default:
                if let _ = loadingText{
                        spec.append(textNode.Spec)
                }
                return .inset([], [8], child: .stack(["v|6",&-.center,_justfy(.center)], childs: spec))
            }
        }
        
    }
    
    public var status = Status.waiting{
        didSet{
            content.status = status
        }
    }
    
    public var direction:Direction = .vertical{
        didSet{
            updateFrame()
        }
    }
    public var content = Content()
    public var size:CGFloat =  60
    
    public var isEnable:Bool = true
    
    
    public weak var scrollView:UIScrollView? = nil{
        didSet{
            scrollView?.addObserver(self, forKeyPath: "contentOffset", options: [.new,], context: nil)
            scrollView?.addObserver(self, forKeyPath: "contentSize", options: [.new,], context: nil)
        
//            preloadDistance = scrollView?.bounds.height ?? 100
        }
    }
    
    open func updateFrame() {
        guard let scrollV = scrollView else {
            return
        }
        switch direction {
            case .vertical:
                let y = max(scrollV.frame.size.height, scrollV.contentSize.height)
                self.frame = CGRect(x: 0, y: y, width: scrollV.frame.width, height: size)
            default:
                let x = max(scrollV.frame.size.width, scrollV.contentSize.width)
                self.frame = CGRect(x: x, y: 0, width: size, height: scrollV.frame.height)
                break
        }
    }
    
    
    open override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        guard let path = keyPath else {
            return
        }
        if (!isEnable){
            return
        }
        DispatchQueue.main.async(execute: {[weak self] in
            guard let ws = self else{return}
           switch path {
               case "contentOffset":
                switch ws.status {
                   case .waiting:
                    ws.checkScroll()
                   default:
                       break
                   }
                   
               case "contentSize":
                ws.updateFrame()
           
               default:
                   break
               }
        })
    }
    
    deinit {
        scrollView?.removeObserver(self, forKeyPath: "contentOffset", context: nil)
        scrollView?.removeObserver(self, forKeyPath: "contentSize", context: nil)
        
        var distance = Sheight
        switch direction {
        case .horizontal:
            distance = 2 * Swidth
        default:
            distance = 2 * Sheight
        }
        preloadDistance = distance

    }
    
    open func checkScroll() {
        guard let scrollV = scrollView else{return}
        let distance = direction.endDistance(scrollView: scrollV)
        if distance < preloadDistance{
            status = .loading
            triggerLoading()
        }
    }
    
    public var triggerLoading:()->Void = {}
    public var preloadDistance:CGFloat = 2 * Sheight



}
